#ifndef ILRT_COLLECTION_H
#define ILRT_COLLECTION_H

#include <ilrt/Type.h>
#include <ilrt/Allocator.h>
#include <illib/LinkedList.h>
#include <illib/Vector.h>
#include <illib/RedBlackTree.h>
#include <ilrt/Numeric.h>

namespace ilrt{
	template<class T> class List;
	template<class T> class ListType : public BasicType {
	protected:
		typedef Allocator::PoolAllocator<List<T> > AllocatorType;
		typedef Allocator::PoolAllocator<typename List<T>::NodeType > NodeAllocatorType;
		AllocatorType allocator_;
		NodeAllocatorType nodeAllocator_;
	public:
		ListType(Runtime & runtime) :
			BasicType(runtime),
			allocator_(this, "List"),
			nodeAllocator_(0, "ListNode")
		{

		}
		AllocatorType & allocator(){return allocator_;}
		NodeAllocatorType & nodeAllocator(){return nodeAllocator_;}
		virtual ~ListType(){

		}
		virtual void destroyType(Runtime & runtime){
		}
		virtual BasicTypedPointer _create()
		{
			return BasicTypedPointer(&allocator_.create(), *this);
		}
		virtual void _destroy(BasicPointer value)
		{
			illib::MemoryTracker::tracker().release(value._value());
		}
	};

	template<class T> class List : public illib::LinkedList::List<T> {
	public:
		typedef illib::LinkedList::Node<T> NodeType;
		List(){

		}
		T* add(size_t index, ListType<T> & type)
		{
			return illib::LinkedList::List<T>::add(index, type.nodeAllocator());
		}
		T* push(ListType<T> & type){return add(0, type);}
		T* head(){
			return illib::LinkedList::List<T>::head();
		}
		void clear(ListType<T> & type){
			illib::LinkedList::List<T>::clear(&type.nodeAllocator());
		}
		size_t length(){return illib::LinkedList::List<T>::length();}
	};

	template<typename T> class ArrayType : public BasicType {
	public:
		typedef Allocator::PoolAllocator<T> AllocatorType;
		typedef Allocator::BlockAllocator<char> BufferAllocatorType;
	protected:
		AllocatorType allocator_;
		BufferAllocatorType blockAllocator_;
	public:
		ArrayType(Runtime & runtime):
			BasicType(runtime),
			allocator_(this, ""),
			blockAllocator_(0, "")
		{

		}
		virtual ~ArrayType(){

		}
		virtual void destroyType(Runtime & runtime){
		}
		virtual BasicTypedPointer _create()
		{
			return BasicTypedPointer(&allocator_.create(), *this);
		}
		virtual void _destroy(BasicPointer value)
		{
			illib::MemoryTracker::tracker().release(value._value());
		}
	};

	template<typename T> class ArrayIterator;
	template<typename T> class Array : illib::Buffer::Vector<T>{
	public:
		typedef ArrayIterator<T> IteratorType;
		Array(){

		}
		void setup(T * data, size_t length){illib::Buffer::Vector<T>::setup(data, length);}
		size_t length(){return illib::Buffer::Vector<T>::length();}
		T* start(){return illib::Buffer::Vector<T>::start();}
	};

	template<typename T> class ArrayIterator : illib::Buffer::Iterator<T>{
	public:
		typedef Array<T> ArrayType;
		ArrayIterator(ArrayType & vector, bool end=false) :
			illib::Buffer::Iterator<T>(vector, end)
		{
		}
		void setup(ArrayType & vector, bool end=false)
		{
			illib::Buffer::Iterator<T>::setup(reinterpret_cast<illib::Buffer::Vector<T> &>(vector), end);
		}
		ArrayIterator() : illib::Buffer::Iterator<T>()
		{
		}
		T* current(){
			return illib::Buffer::Iterator<T>::current();
		}
		T* next(){
			return illib::Buffer::Iterator<T>::next();
		}
		T* prev(){
			return illib::Buffer::Iterator<T>::prev();
		}
		size_t index(){
			return illib::Buffer::Iterator<T>::index();
		}
		T* jump(int jump){
			return illib::Buffer::Iterator<T>::jump(jump);
		}
	};



/*	template<class T> class ArrayType;
	template<class T> class ArrayIterator;
	template<typename T> class Array : illib::Buffer::Vector<T>{
	public:
		typedef T ElementType;
		typedef ilrt::Array<T> ArrayType;
		typedef ArrayIterator<T> IteratorType;
		typedef ilrt::ArrayType<ArrayType> RuntimeType;
		Array(){

		}
		void setup(T * data, size_t length){illib::Buffer::Vector<T>::setup(data, length);}
		size_t length(){return illib::Buffer::Vector<T>::length();}
		T* start(){return illib::Buffer::Vector<T>::start();}
	};

	template<typename T> class ArrayIterator : illib::Buffer::Iterator<T>{
	public:
		typedef T ElementType;
		typedef ilrt::Array<T> ArrayType;
		typedef ArrayIterator<T> IteratorType;
		typedef ilrt::ArrayType<ArrayType> RuntimeType;
		ArrayIterator(ArrayType & vector, bool end=false) :
			illib::Buffer::Iterator<T>(vector, end)
		{
		}
		void setup(ArrayType & vector, bool end=false)
		{
			illib::Buffer::Iterator<T>::setup(reinterpret_cast<illib::Buffer::Vector<T> &>(vector), end);
		}
		ArrayIterator() : illib::Buffer::Iterator<T>()
		{
		}
		T* current(){
			return illib::Buffer::Iterator<T>::current();
		}
		T* next(){
			return illib::Buffer::Iterator<T>::next();
		}
		T* prev(){
			return illib::Buffer::Iterator<T>::prev();
		}
		size_t index(){
			return illib::Buffer::Iterator<T>::index();
		}
		T* jump(int jump){
			return illib::Buffer::Iterator<T>::jump(jump);
		}
	};

	template<class T> class ArrayType : public Type<T> {
	public:
		typedef ArrayType<T> RuntimeType;
		typedef Allocator::PoolAllocator<T> AllocatorType;
		typedef Allocator::BlockAllocator<typename T::ElementType> BufferAllocatorType;
		typedef Pointer<T, typename T::RuntimeType > PointerType;
		typedef TypedPointer<T, typename  T::RuntimeType > TypedPointerType;
	protected:
		AllocatorType allocator_;
		BufferAllocatorType blockAllocator_;
	public:
		ArrayType(Runtime & runtime, const char * name):
			ArrayType::Type(runtime, name),
			allocator_(this, name),
			blockAllocator_(0, name)
		{

		}
		virtual ~ArrayType(){

		}
		virtual void destroyType(Runtime & runtime){
		}
		virtual BasicTypedPointer _create()
		{
			return BasicTypedPointer(&allocator_.create(), *this);
		}
		virtual void _destroy(BasicPointer value)
		{
			illib::MemoryTracker::tracker().release(value._value());
		}
	};

	template<class KT, class VT> class Property{
		KT key_;
		VT value_;
	public:
		typedef KT KeyType;
		typedef VT ValueType;
		Property(){

		}
		KT key(){
			return key_;
		}
		VT value(){
			return value_;
		}
		void key(KT key){
			key_ = key;
		}
		void value(VT value){
			value_ = value;
		}
		void setup(KT &key, VT &value){
			key_ = key;
			value_ = value;
		}
	};

	template<class T> class MapType;
	template<class T> class Map : public illib::RedBlackTree::Tree<T>{
	public:
		typedef T ElementType;
		typedef ilrt::Map<T> MapType;
		typedef illib::RedBlackTree::Iterator<T> IteratorType;
		typedef illib::RedBlackTree::Node<T> NodeType;
		typedef ilrt::MapType<MapType> RuntimeType;
		Map(){

		}
		size_t length(){return MapType::length();}
		void set(BasicPointer key, BasicPointer value);
		BasicPointer get(BasicPointer key);
		BooleanType::PointerType del(BasicPointer key);
		BooleanType::PointerType has(StringType::PointerType key);
	};

	template<class T> class MapType : public Type<T> {
	public:
		typedef MapType<T> RuntimeType;
		typedef Allocator::PoolAllocator<T> AllocatorType;
		typedef Allocator::PoolAllocator<typename T::NodeType> NodeAllocatorType;
		typedef Pointer<T, typename T::RuntimeType > PointerType;
		typedef TypedPointer<T, typename T::RuntimeType > TypedPointerType;
	protected:
		Allocator::PoolAllocator<T> allocator_;
		Allocator::PoolAllocator<typename T::NodeType> nodeAllocator_;
	public:

		MapType(Runtime & runtime, const char * name) :
			MapType::Type(runtime, name),
			allocator_(this, name),
			nodeAllocator_(0, name)
		{

		}
		virtual ~MapType(){

		}
		virtual void destroyType(Runtime & runtime){
		}
		virtual BasicTypedPointer _create()
		{
			return BasicTypedPointer(&allocator_.create(), *this);
		}
		virtual void _destroy(BasicPointer value)
		{
			illib::MemoryTracker::tracker().release(value._value());
		}
	};


	class PointerListType : public PointerList::RuntimeType{
	public:
		PointerListType(Runtime & runtime) : PointerList::RuntimeType(runtime, "PointerList")
		{

		}
	};
	class PointerArray : public Array<BasicPointer>{};
	class PointerArrayType : public PointerArray::RuntimeType{
	public:
		PointerArrayType(Runtime & runtime) : PointerArray::RuntimeType(runtime, "PointerArray")
		{

		}
	};

	class BasicProperty : public Property <BasicPointer, BasicPointer>{};


	class PropertyListType : public PropertyList::RuntimeType{
	public:
		PropertyListType(Runtime & runtime) : PropertyList::RuntimeType(runtime, "PropertyList")
		{

		}
	};
	class PropertyArray : public Array<BasicProperty>{};
	class PropertyArrayType : public PropertyArray::RuntimeType{
	public:
		PropertyArrayType(Runtime & runtime) : PropertyArray::RuntimeType(runtime, "PropertyArray")
		{

		}
	};

	class PropertyMap : public Map<BasicProperty>{};
	class PropertyMapType : public PropertyMap::RuntimeType{
	public:
		PropertyMapType(Runtime & runtime) : PropertyMap::RuntimeType(runtime, "PropertyMap")
		{

		}
	};*/
}

#endif
